package update

import (
	"crypto/tls"
	"log"
	"net/http"

	"flag"
	"fmt"
	"gitee.com/DengAnbang/goutils/loge"
	"github.com/facebookgo/grace/gracehttp"
	"io/ioutil"

	"os"
	"os/exec"
	"strings"
	"time"
)

const UpdateClientHtml = `<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Upload</title>
</head>
<body>
<form method="POST" action="/upload" enctype="multipart/form-data">
   请选择要更新的可执行文件: <input name="file" type="file" />
    <input type="submit" value="上传" />
</form>
</body>
</html>`
const VIDEO_MAX_BYTE = 1024 * 1024 * 1024 //1G
func UpgradeService(addr string, handler *http.ServeMux) error {
	address := flag.String("service", addr, "address to bind to"+addr)
	flag.Parse()
	handler.HandleFunc("/upload", upload)
	handler.HandleFunc("/restartApi", restartApi)
	return gracehttp.Serve(&http.Server{Addr: *address, Handler: handler})
}
func UpgradeServiceTLS(addr string, handler *http.ServeMux, certFile, keyFile string) error {
	address := flag.String("service", addr, "address to bind to"+addr)
	flag.Parse()
	handler.HandleFunc("/upload", upload)
	handler.HandleFunc("/restartApi", restartApi)
	config, err := generateTLSConfig(certFile, keyFile)
	if err != nil {
		return err
	}
	return gracehttp.Serve(&http.Server{
		Addr:      *address,
		Handler:   handler,
		TLSConfig: config,
	})

	//return http.ListenAndServeTLS(addr,
	//	certFile,
	//	keyFile,
	//	handler)
}

func generateTLSConfig(certFile, keyFile string) (*tls.Config, error) {
	cer, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	config := &tls.Config{Certificates: []tls.Certificate{cer}}
	return config, nil
	//cert, err := tls.LoadX509KeyPair("pem", "key")
	////cert, err := tls.LoadX509KeyPair("server.pem", "server.key")
	//if err != nil {
	//	log.Println(err)
	//	return nil, err
	//}
	//certBytes, err := ioutil.ReadFile("pem")
	////certBytes, err := ioutil.ReadFile("client.pem")
	//if err != nil {
	//	return nil, err
	//}
	//clientCertPool := x509.NewCertPool()
	//ok := clientCertPool.AppendCertsFromPEM(certBytes)
	//if !ok {
	//	panic("failed to parse root certificate")
	//}
	//return &tls.Config{
	//	Certificates: []tls.Certificate{cert},
	//	ClientAuth:   tls.RequireAndVerifyClientCert,
	//	ClientCAs:    clientCertPool,
	//}, nil
}
func upload(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		fmt.Fprintln(w, UpdateClientHtml)
	}
	if r.Method == "POST" {

		r.Body = http.MaxBytesReader(w, r.Body, VIDEO_MAX_BYTE)
		err := r.ParseMultipartForm(VIDEO_MAX_BYTE)
		if err != nil {
			fmt.Fprintln(w, err)
			return
		}
		file, h, err := r.FormFile("file")
		if err != nil {
			fmt.Fprintln(w, err)
			return
		}
		bytes, err := ioutil.ReadAll(file)
		if err != nil {
			fmt.Fprintln(w, err)
			return
		}
		backPath := "./back/" + time.Now().Format("200601021504/")
		os.MkdirAll(backPath, 0x777)
		err = ioutil.WriteFile(backPath+h.Filename, bytes, 0x777)
		if err != nil {
			fmt.Fprintln(w, err)
			return
		}
		coverFile(backPath, h.Filename)
		restartApi(w, r)
	}
}
func coverFile(backPath string, fileName string) {
	cpFile := fmt.Sprintf("cp -f %s %s", backPath+fileName, "./back/"+fileName)
	mvFile := fmt.Sprintf("mv -f %s %s", "./back/"+fileName, "./"+fileName)
	commands := []string{cpFile, mvFile}
	for _, str := range commands {
		_, err := ExeCmd(str)
		loge.ENullable(err)
	}
}
func restartApi(w http.ResponseWriter, r *http.Request) {
	command := exec.Command("kill", "-USR2", fmt.Sprintf("%d", os.Getpid()))
	start := command.Start()
	if start != nil {
		loge.ENullable(start)
	}
	fmt.Fprintln(w, "重启完成")
}

func ExeCmd(cmd string) ([]byte, error) {
	parts := strings.Fields(cmd)
	command := exec.Command(parts[0], parts[1:]...)
	return command.CombinedOutput()
}
